use alloc::{string::String, vec::Vec};
use syscall::data::EventStruct;

use crate::fs::get_scheme_by_path;

use super::utils::addr_to_mut_ref;

pub fn fs_read(event: &EventStruct) -> usize {
    let path_buf = unsafe { core::slice::from_raw_parts(event.arg1 as *const u8, event.arg2) };
    let path = unsafe { String::from_utf8_unchecked(path_buf.to_vec()) };

    let offset = event.arg3;

    let buf = unsafe { core::slice::from_raw_parts_mut(event.arg4 as *mut u8, event.arg5) };

    return get_scheme_by_path(path)
        .map(|scheme| scheme.read().read_at(offset, buf))
        .unwrap_or(0);
}

pub fn fs_write(event: &EventStruct) -> usize {
    let path_buf = unsafe { core::slice::from_raw_parts(event.arg1 as *const u8, event.arg2) };
    let path = unsafe { String::from_utf8_unchecked(path_buf.to_vec()) };

    let offset = event.arg3;

    let buf = unsafe { core::slice::from_raw_parts(event.arg4 as *const u8, event.arg5) };

    return get_scheme_by_path(path)
        .map(|scheme| scheme.read().write_at(offset, buf))
        .unwrap_or(0);
}

pub fn fs_fsize(event: &EventStruct) -> usize {
    let path_buf = unsafe { core::slice::from_raw_parts(event.arg1 as *const u8, event.arg2) };
    let path = unsafe { String::from_utf8_unchecked(path_buf.to_vec()) };

    return get_scheme_by_path(path)
        .map(|scheme| scheme.read().size())
        .unwrap_or(0);
}

pub fn fs_list(event: &EventStruct) -> usize {
    let path_buf = unsafe { core::slice::from_raw_parts(event.arg1 as *const u8, event.arg2) };
    let path = unsafe { String::from_utf8_unchecked(path_buf.to_vec()) };

    let ret = get_scheme_by_path(path)
        .map(|scheme| scheme.read().list())
        .unwrap_or(Vec::new());

    let (ptr, len, cap) = ret.into_raw_parts();

    let ret_struct_ptr = alloc::vec![0u8; 24].leak().as_ptr() as usize;
    let ret_ptr = addr_to_mut_ref(ret_struct_ptr);
    *ret_ptr = ptr as usize;
    let len_ptr = addr_to_mut_ref(ret_struct_ptr + 8);
    *len_ptr = len;
    let cap_ptr = addr_to_mut_ref(ret_struct_ptr + 16);
    *cap_ptr = cap;

    ret_struct_ptr as usize
}
